<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Service;

use App\Constants\ErrorCode;
use App\Constants\SuccessCode;
use App\Controller\ProductOrders;
use App\Exception\BusinessException;
use App\Job\UserLevelUpdateJob;
use App\Log\InviteLog;
use App\Model\Account;
use App\Model\Address;
use App\Model\AgentLevel;
use App\Model\Currency;
use App\Model\CurrencyAttention;
use App\Model\FinancePackageOrder;
use App\Model\LoginRecord;
use App\Model\ProductOrder;
use App\Model\Relation\UserRelation;
use App\Model\User;
use App\Model\UserInvite;
use App\Model\UserInviteGrade;
use App\Request\Api\Auth\UserLoginRequest;
use App\Request\Api\Auth\UserLoginUpdatePwdRequest;
use App\Request\Api\Auth\UserMobileUpdateRequest;
use App\Request\Api\Auth\UserPwdUpdateRequest;
use App\Request\Api\Auth\UserRegisterRequest;
use App\Request\Api\UserUpdateRequest;
use App\Resource\BaseResource;
use App\Traits\PwdTool;
use App\Utils\InviteCode;
use Carbon\Carbon;
use Hyperf\DbConnection\Db;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Utils\ApplicationContext;
use HyperfExtension\Jwt\Contracts\JwtFactoryInterface;
use HyperfExtension\Jwt\Contracts\JwtSubjectInterface;

class AuthServer
{
    use PwdTool;

    public function register(UserRegisterRequest $request)
    {
        $user = User::where(['mobile' => $request->input('mobile')])->first();
        if ($user) {
            throw new BusinessException(ErrorCode::AUTH_USER_HAVA_ERROR);
        }

        try {

            $data = $request->inputs(['mobile', 'invite_code', 'password']);

            Db::transaction(function () use ($data) {

                $user = User::create([
                    'mobile' => $data['mobile'],
                    'password_plaintext' => $data['password'],
                    'password' => $this->makePassword($data['password']),
                    'avatar' => \Hyperf\Support\env('HOST_NAME') . '/upload/icon/user_avatar.jpg',
                ]);

                // Registered users open accounts by default
                Account::create([
                    'uid' => $user->id,
                ]);

                if (isset($data['invite_code']) && $data['invite_code'] != '') {

                    $this->invitationUser($user->id, $data['invite_code']);
                }else{

                    $this->invitationUser($user->id, '');
                }

                $invite_code = (new InviteCode())->idToCode($user->id);
                $user->update([
                    'invite_code' => $invite_code,
                    'nick_name' => sprintf("用户_%05d", $user->id),
                    'real_name' => '',
                ]);
            });
            return new BaseResource();
        }catch (\Exception $e) {

            InviteLog::error('用户注册失败::::::::' . $request->input('mobile'));
            InviteLog::error($e->getMessage());

            throw new BusinessException(ErrorCode::AUTH_REGISTER_USER_ERROR);
        }
    }

    public function login(UserLoginRequest $request)
    {
        $user = User::where('mobile', $request->input('mobile'))->first();

        if (!$user) {
            throw new BusinessException(ErrorCode::AUTH_USER_NO_HAVA_ERROR);
        }

        if ($user->is_ban == 1) {
            throw new BusinessException(ErrorCode::AUTH_USER_BAN_ERROR);
        }

        if (!$this->verifyPassword($request->input('password'), $user->password)) {
            throw new BusinessException(ErrorCode::AUTH_PWD_ERROR);
        }

        $header = $request->getHeader('User-Agent');

        $token = $this->getToken($user);

        $updateData = [
            'last_login_ip' => get_client_ip(),
            'last_login_at' => Carbon::now()->toDateTimeString(),
            'user_agent' => !empty($header) ? $header[0] : '',
            'token' => $token['token_type'] . $token['token'],
        ];

        if ($request->input('register_id')) {
            // 以前相同用户极光id 删除
            User::where('register_id', $request->input('register_id'))->where('id', '!=', $user->id)->update([
                'register_id' => '',
            ]);

            $updateData['register_id'] = $request->input('register_id');
        }

        $user->update($updateData);

        $user->token = $token;

        return new \App\Resource\Api\UserResource($user);
    }

    public function getUserInfo(RequestInterface $request)
    {
        $user = User::find(get_app_user()->id);

        return new \App\Resource\Api\UserResource($user);
    }

    public function setUserInfo(UserUpdateRequest $request)
    {
        $data = [];
        if ($request->input('nick_name')) {
            $data['nick_name'] = $request->input('nick_name');
        }
        if ($request->input('real_name')) {
            $data['real_name'] = $request->input('real_name');
        }
        if ($request->input('sex')) {
            $data['sex'] = $request->input('sex');
        }
        if ($request->input('avatar')) {
            $data['avatar'] = $request->input('avatar');
        }
        if ($request->input('address')) {
            $data['address'] = $request->input('address');
        }
        if ($request->input('birthday')) {
            $data['birthday'] = $request->input('birthday');
        }

        if ($data) {
            get_app_user()->update($data);
        }

        return new BaseResource(SuccessCode::UPDATE_SUCCESS);
    }

    public function refreshToken(RequestInterface $request)
    {
        $token = $this->getToken(get_app_user());
        User::find(get_app_user()->id)->update([
            'token' => $token['token_type'] . $token['token'],
        ]);
        return new BaseResource(SuccessCode::SUCCESS, $token);
    }

    public function updatePwd(UserPwdUpdateRequest $request)
    {
        if ($request->input('password_one') != $request->input('password_two')) {
            throw new BusinessException(ErrorCode::PWD_SAME_ERROR);
        }
        // 验证密码
        $old_password =  $request->input('old_password');
        if (!$this->verifyPassword($old_password, get_app_user()->password)) {
            throw new BusinessException(ErrorCode::AUTH_USER_OLD_PASSWORD_ERROR);
        }

        // 更改密码后 重新登录
        get_app_user()->update([
            'password' => $this->makePassword($request->input('password_one')),
            'password_plaintext' => $request->input('password_one')
        ]);

        return new BaseResource(SuccessCode::PASSWORD_SUCCESS);
    }

    public function getToken(JwtSubjectInterface $user)
    {
        $jwt = ApplicationContext::getContainer()->get(JwtFactoryInterface::class);
        $jwt = $jwt->make();
        $token = $jwt->fromUser($user);

        return [
            'token' => $token,
            'token_type' => 'Bearer ',
            'exp' => time() + config('jwt.ttl'),
        ];
    }

    public function registerUser($mobile, $invicode)
    {
        $user = User::create([
            'mobile' => $mobile,
            'password_plaintext' => 'qwe123456',
            'password' => $this->makePassword('qwe123456'),
            'avatar' => \Hyperf\Support\env('HOST_NAME') . '/upload/icon/user_avatar.jpg',
        ]);

        Account::create([
            'uid' => $user->id,
            'balance_usable' => 10000,
        ]);

        Address::create([
            'id' => $user->id,
            'uid' => $user->id,
            'user_name' => '李先生',
            'mobile' => '18653009825',
            'region' => '121212',
            'address' => '北京海淀',
        ]);

        $this->invitationUser($user->id, $invicode);

        $invite_code = (new InviteCode())->idToCode($user->id);
        $user->update([
            'invite_code' => $invite_code,
            'nick_name' => sprintf("%08d", $user->id),
        ]);

        return $user->id;
    }


    /*
     * $uid  Current registered user
     * $invite_code Inviter User invitation code
     */
    public function invitationUser($uid, $invite_code)
    {
        try {
            // Example Initialize the level user information
            for($i = 1; $i <= 100; $i++) {

                UserInviteGrade::create([
                    'grade' => $i,
                    'uid' => $uid,
                    'is_full' => 2,
                    'child_nums' => 0,
                    'child_nodes' => [],
                ]);
            }

          if ($invite_code == '') {

              UserInvite::create([
                  'uid' => $uid,
                  'invitation_uid' => 0,
                  'root_uid' => 0,
                  'left_uid' => 0,
                  'center_uid' => 0,
                  'right_uid' => 0,
                  'parent_nodes' => [],
                  'child_nodes' => [],
                  'effective_child_nodes' => [],
              ]);

              InviteLog::info('用户ID: ' . $uid . '创建');
          } else {

             $user = User::where('invite_code', $invite_code)->first();

             $invitU = UserInvite::where('uid', $user->id)->first();

             InviteLog::info(json_encode($invitU->parent_nodes));

             if (count($invitU->parent_nodes) > 0) {

                 $tmp = $invitU->parent_nodes;
                 $root_uid = end($tmp);
                 UserInvite::create([
                     'uid' => $uid,
                     'invitation_uid' => $user->id,
                     'root_uid' => $root_uid,
                     'parent_nodes' => array_merge([$invitU->uid], $invitU['parent_nodes']),
                     'child_nodes' => [],
                 ]);
             } else {

                 $root_uid = $user->id;
                 UserInvite::create([
                     'uid' => $uid,
                     'invitation_uid' => $user->id,
                     'root_uid' => $root_uid,
                     'parent_nodes' => [$invitU->uid],
                     'child_nodes' => [],
                 ]);
             }

             InviteLog::info('用户直推用户 ' . $user->id);
             InviteLog::info('根据父id组合 逐个取出 设置  00');
             $userI = UserInvite::where('uid', $uid)->first();

             // 根据父id组合 逐个取出 设置
             foreach ($userI->parent_nodes as $k => $v) {
                 $nextGrade = UserInviteGrade::where('uid', $v)->where('grade', $k + 1)->first();

                 $childs = array_merge($nextGrade['child_nodes'], [$uid]);
                 $nextGrade->child_nodes = $childs;
                 $nextGrade->child_nums = count($childs);
                 $nextGrade->save();
             }

             InviteLog::info('根据父id组合 逐个取出 设置   01');
             InviteLog::info(json_encode($userI->parent_nodes));

             // Process the parent user's relational data
             $json_parent_nodes = str_replace(']', ')', str_replace('[', '(', json_encode($userI->parent_nodes)));

             // Update valid children of all parent nodes
             Db::update('UPDATE user_invite set child_nodes = json_ARRAY_APPEND( child_nodes, "$", ' . $uid . ') WHERE uid in ' . $json_parent_nodes);
           }

            InviteLog::info('处理成功');
        }catch (Exception $e){

            InviteLog::info('用户关联失败');
            InviteLog::info($e->getMessage());
        }
    }
}
